/***********************************************************************************
 * 文件名： polsys_lib.c
 * 作者： 刘言
 * 版本： 1
 * 说明：
 *      常用的一些数据处理相关的宏定义和函数。polsys.h中已经默认包含。
 * 修改记录：
 * 	2021/01/23: 初版。 刘言。
***********************************************************************************/
#include "polsys_lib.h"



char IntToHexChar(u8 b)
{
	if(b >= 10) return ('A' - 10 + b);
	else return ('0' + b);
}

char * ToHexStr(char * str_dest, const void *src, int bytes_len)
{
	char *p = str_dest;
	int i;
	u8 t;
	for(i = 0; i < bytes_len; i++)
	{
		t = ((u8 *)src)[i];
		p[0] = IntToHexChar(t >> 4);
		p[1] = IntToHexChar(t & 0x0F);
		p += 2;
	}
	p[0] = '\0';
	return str_dest;
}

char * ToHexStrE(char * str_dest, const void *src, int bytes_len, u8 end_data)
{
	char *p = str_dest;
	int i;
	u8 t;
	for(i = 0; i < bytes_len; i++)
	{
		t = ((u8 *)src)[i];
		if(t == end_data) break;
		p[0] = IntToHexChar(t >> 4);
		p[1] = IntToHexChar(t & 0x0F);
		p += 2;
	}
	p[0] = '\0';
	return str_dest;
}

int GetDataFromHexStr(const char *str)
{
	int num=0;
	uint8_t fh;
	if(*str=='-')
	{
		fh=0;	//负数
		str++;
	}
	else fh=1;
	while(*str)
	{
		if(*str >= '0' && *str <= '9')
		{
			num<<=4;
			num+=*str-'0';
		}
		else if(*str >= 'A' && *str <= 'F')
		{
			num<<=4;
			num+=*str-'A'+10;
		}
		else break;
		str++;
	}
	if(fh==0)num=-num;
	return num;
}

int GetDataFromDecStr(const char *str)
{
	int num=0;
	uint8_t fh;
	if(*str=='-')
	{
		fh=0;	//负数
		str++;
	}
	else fh=1;
	while(*str)
	{
		if(*str >= '0' && *str <= '9')
		{
			num=num*10;
			num+=*str-'0';
		}
		else break;
		str++;
	}
	if(fh==0)num=-num;
	return num;
}

int IntPow(int base, u16 pow)
{
	int result = 1;
	for(u16 i = 0; i < pow; i++)
	{
		result *= base;
	}
	return result;
}

u16 IntSqrt(u32 value)
{
	u16 root;
	u16 rem;
	u8 i;
	for(root = rem = i = 0; i < 16; ++i)
	{
		int if1;
		root <<= 1;
		rem = (rem << 2) | (value >> 30);
		value <<= 2;
		if1 = (root << 1) + 1;
		if(rem >= if1)
		{
			root |= 1;
			rem -= if1;
		}
	}
	return root;
}

// 牛顿逼近法
// static u32 IntSqrtInit(float f)
// {
// 	u32 ret;
// 	u32 data = *(u32 *)&f;
// 	const int exp = ((data >> 23) & (0x0ff)) - 127;
// 	const int tail = data & ((1<<23)-1);
// 	ret = *(float *)&ret;
// 	if(exp & 1) ret += ret >> 1;
// 	return ret;
// }
// // 仅在ARM测试
// u16 IntSqrt(u32 y)
// {
// 	unsigned x[2];
// 	if(y <= 1) return y;
// 	x[0] = IntSqrtInit(y);
// 	x[1] = x[0] + (x[0] >> 1);
// 	while(x[0] != x[1])
// 	{
// 		x[1] = x[0];
// 		x[0] = (y / x[0] + x[0]) >> 1;
// 	}
// 	return x[0];
// }

// 获取最大值
u8 GetMaxU8(u8 *dat, int len)
{
	int i;
	u8 max = 0;
	for(i=0; i<len; i++)
	{
		if(dat[i] > max) max = dat[i];
	}
	return max;
}

// 获取最大值
u16 GetMaxU16(u16 *dat, int len)
{
	int i;
	u16 max = 0;
	for(i=0;i<len;i++)
	{
		if(dat[i]>max)max = dat[i];
	}
	return max;
}

// 波形数据平滑处理，积分运算消除突变
void SmoothWaveU16(u16 *dat, int len)
{
	int i;
	for(i=1;i<len;i++)
	{
		dat[i] = (dat[i] + dat[i-1])/2;
	}
}

// 获得16位绝对值
IN_LINE u16 GetAbsS16(s16 v)
{
	if(v < 0)return -v;
	else return v;
}

// 获得32位校验和
u32 GetSum_U32(const u8 *buff, u32 len)
{
	u32 i;
	u32 sum = 0;
	for (i = 0; i < len; i++)
	{
		sum += buff[i];
	}
	return sum;
}

// 获得8位校验和
u8 GetSum_U8(const u8 *buff, u8 len)
{
	u8 i;
	u8 sum = 0;
	for (i = 0; i < len; i++)
	{
		sum += buff[i];
	}
	return sum;
}

static pdata u32 mRand; // 8bit伪随机数 mRand掉电保存随机性更强
// 生成8bit随机数
u8 GetRand8bit(void)
{
	u32 temp = mRand;
	do
	{
		// 防止为0
		if (temp == 0)
			temp = 0x4B07;
		temp ^= (temp << 13);
		temp ^= (temp >> 17);
		temp ^= (temp << 5);
		mRand = temp;
		temp = (temp >> 16) & 0x00FF;
	} while (temp == 0);
	// 保存mRand;
	return (u8)(temp);
}

bool IsInRangeU16(u16 num, u16 start, u16 end)
{
	return ((num >= start) && (num <= end));
}

////把数据分离成单个字节，高字节在前（0）
//void SplitDWard(u32 a,u8 * b)
//{
//		b[3] = (u8)(a >> 24);
//		b[2] = (u8)(a >> 16);
//		b[1] = (u8)(a >> 8);
//		b[0] = (u8)a;
//}

//把字节数组的成员合并成1个u32整数 0[3] 1[2] 2[1] 3[0]
u32 MakeU32(u8 *Bytes, u8 Lenght)
{
	u8 yw = 0;
	u8 index;
	u32 r = 0;
	u8 i;

	if (Lenght > 4)
		return 0;
	index = Lenght - 1;

	for (i = 0; i < Lenght; i++)
	{
		r += ((u32)Bytes[index] << yw);
		yw += 8;
		index--;
	}
	return r;
}

/****************************************************************************
* 名    称：u8 DecToBcd(u8 dat)
* 功    能：将普通数据转换成高4位存放十位，低4位存放个位的BCD码。
* 入口参数：dat：想要转换的数据
* 出口参数：转换完成的数据
* 说    明：如 55-->0x55
* 调用方法：bcdnum=DecToBcd(num);
****************************************************************************/
u8 DecToBcd(u8 dat)
{
	u8 temp;
	temp = dat / 10;
	dat = dat % 10;
	temp = (temp << 4) + dat;
	return temp;
}
/****************************************************************************
* 名    称：u8 BcdToDec(u8 dat)
* 功    能：将高4位存放十位，低4位存放个位的BCD码转换为普通数据。
* 入口参数：dat：想要转换的数据
* 出口参数：转换完成的数据
* 说    明：如 0x55-->55
* 调用方法：num=BcdToDec(bcdnum);
****************************************************************************/
u8 BcdToDec(u8 dat)
{
	u8 dat1;
	dat1 = dat / 16;
	dat = dat % 16;
	dat1 = dat + dat1 * 10;
	return dat1;
}

/*********************************************************************
* 名    称: u8 MedianFilter8b9(u8 *dat)
* 功    能: 中值滤波
* 入口参数: 数组首地址
* 出口参数: 结果
* 说    明: 8bit 9次
* 调用方法: ADVolue = MedianFilter8b9(datbuff);
**********************************************************************/
u8 MedianFilter8b9(u8 *dat)
{
	u8 i, j, k;
	u8 temp;

	for (i = 0; i < 8; i++) //排序
	{
		k = i;
		for (j = k + 1; j < 9; j++)
		{
			if (dat[k] > dat[j])
				k = j;
		}
		temp = dat[k];
		dat[k] = dat[i];
		dat[i] = temp;
	}
	temp = ((u16)dat[3] + (u16)dat[4] + (u16)dat[5]) / 3; //取中间值
	return (temp);
}

/*********************************************************************
* 名    称: u16 MedianFilter16b9(u16 *dat)
* 功    能: 中值滤波
* 入口参数: 数组首地址
* 出口参数: 结果
* 说    明: 16bit 9次
* 调用方法: ADVolue = MedianFilter16b9(datbuff);
**********************************************************************/
u16 MedianFilter16b9(u16 *dat)
{
	u8 i, j, k;
	u16 temp;

	for (i = 0; i < 8; i++) //排序
	{
		k = i;
		for (j = k + 1; j < 9; j++)
		{
			if (dat[k] > dat[j])
				k = j;
		}
		temp = dat[k];
		dat[k] = dat[i];
		dat[i] = temp;
	}
	temp = ((u32)dat[3] + (u32)dat[4] + (u32)dat[5]) / 3; //取中间值
	return (temp);
}

/*********************************************************************
* 名    称: u16 MedianFilter16b20(u16 *dat)
* 功    能: 中值滤波
* 入口参数: 数组首地址
* 出口参数: 结果
* 说    明: 16bit 20次
* 调用方法: ADVolue = MedianFilter16b20(datbuff);
**********************************************************************/
u16 MedianFilter16b20(u16 *dat)
{
	u8 i, j, k;
	u16 temp;
	u32 add = 0;

	for (i = 0; i < 19; i++) //排序
	{
		k = i;
		for (j = k + 1; j < 20; j++)
		{
			if (dat[k] > dat[j])
				k = j;
		}
		temp = dat[k];
		dat[k] = dat[i];
		dat[i] = temp;
	}
	for(i = 6; i < 14; i++)	// 求和
	{
		add += dat[i];
	}
	temp = add / 8; 	//平均
	return (temp);
}

u16 MedianFilter16bn(u16 *dat, int num)
{
	u8 i, j, k;
	u16 temp;
	u32 add = 0;

	if(num%2)num--;
	if(num == 0) return dat[0];
	else if(num == 2) return dat[1];

	for (i = 0; i < num - 1; i++) //排序
	{
		k = i;
		for (j = k + 1; j < num; j++)
		{
			if (dat[k] > dat[j])
				k = j;
		}
		temp = dat[k];
		dat[k] = dat[i];
		dat[i] = temp;
	}
	for(i = num/4; i < num - num/4; i++)	// 求和
	{
		add += dat[i];
	}
	temp = add / (num / 2); 	//平均
	return (temp);
}
